﻿using System;
using System.Linq;
using Hxsoft.AppV1;

namespace Hxsoft.AppV1.Module
{
	public static class RolePermissions
	{
		#region GetRolesIsHasCategoryPermission
		/// <summary>
		/// 获取指定的角色列表中的任一角色是否有指定资源类别下的任何一项资源的指定权限。
		/// </summary>
		/// <param name="o">角色权限集合。</param>
		/// <param name="roleNames">指定的角色列表。</param>
		/// <param name="categoryId">指定的资源类别标识。</param>
		/// <param name="permissionCode">指定的权限码。</param>
		/// <param name="siteId">权限的站点范围。</param>
		/// <returns>布尔值表示角色是否有指定资源类别下的任何一项资源的指定权限。</returns>
		public static bool GetRolesIsHasCategoryPermission(this System.Data.Linq.Table<RolePermission> o, string[] roleNames, Guid categoryId, int permissionCode, int? siteId)
		{
			if (roleNames.Contains(Roles.AdministratorRoleName)) return true;

			var q = from p in o
					where p.IsEnabled == true
						&& p.CategoryId == categoryId
						&& p.PermissionCode == permissionCode
						&& roleNames.Contains(p.RoleName)
					select p;

			if (siteId.HasValue)
				return q.Any(p => p.SiteId == siteId.Value || p.SiteId == null);
			return q.Any(p => p.SiteId == null);
		}

		/// <summary>
		/// 获取指定的角色列表中的任一角色是否有指定资源类别下的任何一项资源的指定权限（不受站点限制）。
		/// </summary>
		/// <param name="o">角色权限集合。</param>
		/// <param name="roleNames">指定的角色列表。</param>
		/// <param name="categoryId">指定的资源类别标识。</param>
		/// <param name="permissionCode">指定的权限码。</param>
		/// <returns>布尔值表示角色是否有指定资源类别下的任何一项资源的指定权限。</returns>
		public static bool GetRolesIsHasCategoryPermission(this System.Data.Linq.Table<RolePermission> o, string[] roleNames, Guid categoryId, int permissionCode)
		{
			if (roleNames.Contains(Roles.AdministratorRoleName)) return true;

			var q = from p in o
					where p.IsEnabled == true
						&& p.CategoryId == categoryId
						&& p.PermissionCode == permissionCode
						&& roleNames.Contains(p.RoleName)
					select p;

			return q.Any();
		}
		#endregion


		#region GetRolesIsHasPermission
		/// <summary>
		/// 获取指定的角色列表中的任一角色是否有指定的权限。
		/// </summary>
		/// <param name="o">角色权限集合。</param>
		/// <param name="roleNames">指定的角色列表。</param>
		/// <param name="resourceId">资源标识。</param>
		/// <param name="permissionCode">权限码。</param>
		/// <param name="siteId">权限的站点范围。</param>
		/// <returns>布尔值表示指定的角色列表中的任一角色是否有指定的权限。</returns>
		public static bool GetRolesIsHasPermission(this System.Data.Linq.Table<RolePermission> o, string[] roleNames, Guid resourceId, int permissionCode, int? siteId)
		{
			if (roleNames.Contains(Roles.AdministratorRoleName)) return true;

			var q = from p in o
					where p.IsEnabled == true
						&& p.ResourceId == resourceId
						&& p.PermissionCode == permissionCode
						&& roleNames.Contains(p.RoleName)
					select p;

			if (siteId.HasValue)
				return q.Any(p => p.SiteId == siteId.Value || p.SiteId == null);
			return q.Any(p => p.SiteId == null);
		}

		/// <summary>
		/// 获取指定的角色列表中的任一角色是否有指定的权限。（不受站点限制）。
		/// </summary>
		/// <param name="o">角色权限集合。</param>
		/// <param name="roleNames">指定的角色列表。</param>
		/// <param name="resourceId">资源标识。</param>
		/// <param name="permissionCode">权限码。</param>
		/// <returns>布尔值表示指定的角色列表中的任一角色是否有指定的权限。</returns>
		public static bool GetRolesIsHasPermission(this System.Data.Linq.Table<RolePermission> o, string[] roleNames, Guid resourceId, int permissionCode)
		{
			if (roleNames.Contains(Roles.AdministratorRoleName)) return true;

			var q = from p in o
					where p.IsEnabled == true
						&& p.ResourceId == resourceId
						&& p.PermissionCode == permissionCode
						&& roleNames.Contains(p.RoleName)
					select p;

			return q.Any();
		}
		#endregion


		/// <summary>
		/// 获取指定的角色列表中的任一角色是否拥有指定站点列表的任意一个的特定权限。
		/// </summary>
		/// <param name="o">角色权限集合。</param>
		/// <param name="roleNames">指定的角色列表。</param>
		/// <param name="resourceId">资源标识。</param>
		/// <param name="permissionCode">权限码。</param>
		/// <param name="siteIds">权限的站点范围。</param>
		/// <returns>布尔值表示指定的角色列表中的任一角色是否拥有指定站点的任意一个的特定权限。</returns>
		public static bool GetRolesIsHasAnySitePermission(this System.Data.Linq.Table<RolePermission> o, string[] roleNames, Guid resourceId, int permissionCode, int[] siteIds)
		{
			if (roleNames.Contains(Roles.AdministratorRoleName)) return true;
			if (GetRolesIsHasPermission(o, roleNames, resourceId, permissionCode, null)) return true;

			var q = from p in o
					where p.IsEnabled == true
						&& p.ResourceId == resourceId
						&& p.PermissionCode == permissionCode
						&& roleNames.Contains(p.RoleName)
						&& (p.SiteId.HasValue && siteIds.Contains(p.SiteId.Value))
					select p;

			return q.Any();
		}

		/// <summary>
		/// 获取指定的角色列表中的任一角色是否有指定的站点列表的所有站点特定的权限。
		/// </summary>
		/// <param name="o">角色权限集合。</param>
		/// <param name="roleNames">指定的角色列表。</param>
		/// <param name="resourceId">资源标识。</param>
		/// <param name="permissionCode">权限码。</param>
		/// <param name="siteIds">权限的站点范围。</param>
		/// <returns>布尔值表示指定的角色列表中的任一角色是否有指定的站点列表的所有站点特定的权限。</returns>
		public static bool GetRolesIsHasEverySitePermission(this System.Data.Linq.Table<RolePermission> o, string[] roleNames, Guid resourceId, int permissionCode, int[] siteIds)
		{
			if (roleNames.Contains(Roles.AdministratorRoleName)) return true;
			if (GetRolesIsHasPermission(o, roleNames, resourceId, permissionCode, null)) return true;

			siteIds = siteIds.Distinct().ToArray();

			var q = from p in o
					where p.IsEnabled == true
						&& p.ResourceId == resourceId
						&& p.PermissionCode == permissionCode
						&& roleNames.Contains(p.RoleName)
						&& (p.SiteId.HasValue && siteIds.Contains(p.SiteId.Value))
					group p by p.SiteId into g
					select g.Key;

			return siteIds.All(id => q.ToArray().Contains(id));
		}
	}
}